package com.zoe.vhr.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.zoe.vhr.config.RabbitCallBack;
import com.zoe.vhr.enums.MailConfigEnum;
import com.zoe.vhr.mapper.EmployeeMapper;
import com.zoe.vhr.model.Employee;
import com.zoe.vhr.model.MailSendLog;
import com.zoe.vhr.service.EmployeeService;
import com.zoe.vhr.service.MailSendLogService;
import com.zoe.vhr.utils.RabbitUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

/**
 * @Author Zoe.Zhang
 * @Date: 2021/08/08
 * @Description 员工
 */
@Slf4j
@Service
public class EmployeeServiceImpl implements EmployeeService {
    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Resource
    private MailSendLogService mailSendLogService;

    @Override
    public List<Employee> listAllEmp(Employee employee) {
        return employeeMapper.listAllEmp(employee);
    }

    @Override
    public List<Employee> listEmpPages(Integer pageNum, Integer pageSize, Employee employee) {
        PageHelper.startPage(pageNum, pageSize);
        return this.listAllEmp(employee);
    }

    @Override
    public String getMaxWorkId() {
        Integer integer = Convert.toInt(employeeMapper.getMaxWorkId());
        integer += 1;
        String workId = StrUtil.padPre(integer + "", 8, "0");
        return workId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int saveEmp(Employee employee) {
        Date beginContract = employee.getBeginContract();
        Date endContract = employee.getEndContract();
        // 计算相差天数
        long between = DateUtil.between(beginContract, endContract, DateUnit.DAY, true);
        BigDecimal start = Convert.toBigDecimal(between);
        BigDecimal difference = Convert.toBigDecimal(365);
        Double s = Convert.toDouble(start.divide(difference, 2, RoundingMode.HALF_UP));
        employee.setContractTerm(s);
        employee.setWorkState("在职");
        int count = employeeMapper.insert(employee);

        if (count > 0) {
            Integer empID = employee.getId();
            // 发送出去的对象,包括对象内部依赖的实体类,全部都需要实现序列化接口
            Employee resEmp = employeeMapper.selectEmpById(empID);
            // 保存消息发送日志
            MailSendLog mailSendLog = new MailSendLog();
            String msgId = IdUtil.fastUUID();
            mailSendLog.setMsgId(msgId);
            mailSendLog.setEmpId(empID);
            // 标记消息为发送中的状态
            mailSendLog.setStatus(MailConfigEnum.SENDING);
            mailSendLog.setExchange(MailConfigEnum.MAIL_EXCHANGE_NAME);
            mailSendLog.setRouteKey(MailConfigEnum.MAIL_ROUTING_KEY);
            mailSendLog.setCreateTime(DateUtil.date());
            mailSendLog.setTryTime(new Date(System.currentTimeMillis() + MailConfigEnum.MSG_TIME_OUT));
            mailSendLogService.insertSelective(mailSendLog);

            CorrelationData correlationData = new CorrelationData(msgId);
            // 设置队列->交换机的回调
            correlationData.getFuture().addCallback(
                    RabbitCallBack.getConfirmSuccessCallback(msgId, correlationData),
                    RabbitCallBack.getFailureCallback(msgId, correlationData)
            );

            // 正常发送消息
            rabbitTemplate.convertAndSend(MailConfigEnum.MAIL_EXCHANGE_NAME, MailConfigEnum.MAIL_ROUTING_KEY, resEmp, RabbitUtil.customMsgId(msgId), correlationData);
            // 演示消息幂等处理
            // rabbitTemplate.convertAndSend(MailConfigEnum.MAIL_EXCHANGE_NAME, MailConfigEnum.MAIL_ROUTING_KEY, resEmp, correlationData);

            // 往不存在的交换机发送消息, 看看能不能触发消息发布确认机制
            // rabbitTemplate.convertAndSend("不存在的交换机", MailConfigEnum.MAIL_ROUTING_KEY, resEmp, RabbitUtil.customMsgId(msgId), correlationData);

            // 交换机存在,路由key不存在
            // rabbitTemplate.convertAndSend(MailConfigEnum.MAIL_EXCHANGE_NAME, MailConfigEnum.MAIL_ROUTING_KEY + "1", resEmp, RabbitUtil.customMsgId(msgId), correlationData);
        }
        return count;
    }


    @Override
    public int updateEmp(Employee employee) {
        Date beginContract = employee.getBeginContract();
        Date endContract = employee.getEndContract();
        // 计算相差天数
        long between = DateUtil.between(beginContract, endContract, DateUnit.DAY, true);
        BigDecimal start = Convert.toBigDecimal(between);
        BigDecimal difference = Convert.toBigDecimal(365);
        Double s = Convert.toDouble(start.divide(difference, 2, RoundingMode.HALF_UP));
        employee.setContractTerm(s);
        return employeeMapper.updateByPrimaryKeySelective(employee);
    }

    @Override
    public int deleteEmp(Integer empId) {
        return employeeMapper.deleteByPrimaryKey(empId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int saveEmpByExcel(List<Employee> employeeList) {
        int count = 0;
        try {
            count = employeeMapper.saveEmpByExcel(employeeList);
        }
        catch (Exception e) {
            throw new RuntimeException("导入异常");
        }
        return count;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int deleteBatchEmpByIds(Integer[] empIds) {
        return employeeMapper.deleteBatchEmpByIds(empIds);
    }

    @Override
    public Employee getById(Integer empId) {
        return employeeMapper.selectEmpById(empId);
    }
}
